home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / Source / KeyCapApp 2.0 Source / kcapApp.c < prev    next >
C/C++ Source or Header  |  1993-12-07  |  19KB  |  723 lines

  1. /* kcapApp */
  2. /* demonstration keyboard drawing from KCAP resource */
  3.  
  4. /* Greg Robbins 12/91 */
  5. /* Matthew Mora 12/93 */
  6. /* includes code stolen from Bo3b's TubeTest */
  7.  
  8. /* version 1.1, 2/92: uses RGetResource rather than GetResource for KCAP;
  9.                   gets KCHR number from script manager */
  10.  
  11. /* version 1.2, 2/92: adds menu of KCAP IDs, displays virtual keycodes */
  12.                   
  13. /* version 2.0  , 12/93: adds color and modifer keys  MXM */
  14.  
  15.  
  16. #include <Types.h>
  17. #include <Memory.h>
  18. #include <Quickdraw.h>
  19. #include <Fonts.h>
  20. #include <Events.h>
  21. #include <Menus.h>
  22. #include <Windows.h>
  23. #include <Resources.h>
  24. #include <Dialogs.h>
  25. #include <Desk.h>
  26. #include <Scrap.h>
  27. #include <OSUtils.h>
  28. #include <ToolUtils.h>
  29. #include <SegLoad.h>
  30. #include <SysEqu.h>
  31. #include <Script.h>
  32. #include <Packages.h>
  33. #include <String.h>
  34. //#include <Strings.h>
  35. #include <Folders.h>
  36.     
  37. /* Constants */
  38. #define appleID                1000            /* resource IDs/menu IDs for Apple, */
  39. #define fileID                1001            /*     File and */
  40. #define editID                1002            /*    Edit menus */
  41. #define displayID            1003
  42.  
  43. #define appleM                0                /* Index for each menu in myMenus (array of menu handles) */
  44. #define fileM                1
  45. #define editM                2
  46. #define displayM        3
  47.  
  48. #define menuCount            4                /* Total number of menus */
  49.  
  50. #define windowID            1000            /* Resource ID for main window */
  51. #define aboutMeDLOG         1000            /* And Resource ID for About box dialog. */
  52.  
  53. #define quitItem            1                /* Quit in the File menu */
  54.  
  55. #define aboutMeCommand        1                /* Menu item in apple menu for About */
  56.     
  57. typedef struct {
  58.         Rect keyRect;
  59.         char keyCode;
  60.         char Ascii;
  61. } KeyDataRec;
  62.  
  63. #pragma mark /* Globals */
  64.     RGBColor    backGroundGray,liteGray,drkGray,tinge;
  65. MenuHandle myMenus[menuCount];
  66. Rect dragRect;
  67. Boolean    doneFlag;
  68. EventRecord    myEvent;
  69. WindowPtr    myWindow, whichWindow;
  70. char theChar;
  71. TEHandle gMyTE;
  72.  
  73. Boolean    gKeycodesFlag = false;
  74. short    gKcapNum, gCurrDisplayItem;
  75. KeyDataRec myKeys[256];
  76. short    gNumberOfKeys=0;
  77. long oldModifiers = 0;
  78.  
  79.  
  80. void SetUpMenus();
  81. void DoCommand(long int mResult);
  82. void DrawKeyCaps(short modifiers, short kcharNum, short kcapNum, Boolean keycodesFlag);
  83.  
  84. //--------------------------------------
  85.     void InitMac()
  86. //--------------------------------------
  87.     
  88.  
  89. {    
  90.     SysEnvRec gMac;
  91.     
  92.     InitGraf(&qd.thePort);
  93.     InitFonts();
  94.     InitWindows();
  95.     InitMenus();
  96.     TEInit();
  97.     InitDialogs(nil);
  98.     InitCursor();
  99.     SysEnvirons(2,&gMac);
  100.     if (!gMac.hasColorQD)
  101.         ExitToShell();
  102.         
  103. }
  104. //--------------------------------------
  105.     void InitApp()
  106. //--------------------------------------
  107. {
  108.     Rect r;
  109.     SetRect(&dragRect, 4, 24, qd.screenBits.bounds.right - 4, qd.screenBits.bounds.bottom - 4);
  110.     doneFlag = false;                            /* flag to detect when Quit command is chosen */
  111.  
  112.     myWindow = GetNewCWindow(windowID, nil, (WindowPtr) -1);
  113.     SetPort(myWindow);
  114.     
  115.     SetRect(&r,0,0,100,20);
  116.     gMyTE = TENew(&r,&r);
  117.  
  118.     TEActivate(gMyTE);
  119.     liteGray.red = 
  120.     liteGray.green = 
  121.     liteGray.blue = 56797;    
  122.     
  123.     tinge.red = 
  124.     tinge.green = 
  125.     tinge.blue = 61166L;        
  126.     
  127.     backGroundGray.red = 
  128.     backGroundGray.green  =
  129.     backGroundGray.blue = 52428L;
  130.     
  131.     drkGray.red =
  132.     drkGray.green = 
  133.     drkGray.blue = 34592L;
  134.  
  135. }
  136.  
  137. //--------------------------------------
  138.     CheckForKeyPress(Point pt)
  139. //--------------------------------------
  140. {
  141.     short i;
  142.     
  143.     GlobalToLocal(&pt);
  144.     for (i=0;i<gNumberOfKeys;i++){
  145.         if (PtInRect(pt,&myKeys[i].keyRect)) {
  146.             Rect r = myKeys[i].keyRect;
  147.             InsetRect(&r,1,1);
  148.             InvertRect(&r);
  149.             while (Button()) ;
  150.             InvertRect(&r);
  151.             TEKey(myKeys[i].Ascii,gMyTE);
  152.             i=gNumberOfKeys;
  153.             
  154.             
  155.         }
  156.     }
  157. }
  158. //--------------------------------------
  159.     CheckForKeyTyped(char theChar)
  160. //--------------------------------------
  161. {
  162.     short i;
  163.     long n;
  164.     
  165.  
  166.     for (i=0;i<gNumberOfKeys;i++){
  167.         if (myKeys[i].keyCode == theChar) {
  168.             Rect r = myKeys[i].keyRect;
  169.             InsetRect(&r,1,1);
  170.             InvertRect(&r);
  171.             Delay(5,&n);
  172.             InvertRect(&r);
  173.             TEKey(myKeys[i].Ascii,gMyTE);
  174.             i=gNumberOfKeys;
  175.             
  176.             
  177.         }
  178.     }
  179. }
  180.  
  181. //--------------------------------------
  182.     main()
  183. //--------------------------------------
  184. {
  185.     Str255 tempStr, tempStr2;
  186.     StringHandle tempStrHandle;
  187.  
  188.     InitMac();
  189.     InitApp();
  190.     
  191.     SetUpMenus();
  192.     
  193.     /*
  194.     **    Main Event Loop
  195.     */
  196.     do {
  197.         if (WaitNextEvent(everyEvent, &myEvent, 50, nil)) {
  198.             
  199.             switch (myEvent.what) {                /* case on event type */
  200.  
  201.                 case mouseDown:
  202.                     switch (FindWindow(myEvent.where, &whichWindow)) {
  203.  
  204.                         case inSysWindow:        /* desk accessory window: call Desk Manager to handle it */
  205.                             SystemClick(&myEvent, whichWindow);
  206.                             break;
  207.  
  208.                         case inMenuBar:            /* Menu bar: learn which command, then execute it. */
  209.                             DoCommand(MenuSelect(myEvent.where));
  210.                             break;
  211.  
  212.                         case inDrag:            /* title bar: call Window Manager to drag */
  213.                             DragWindow(whichWindow, myEvent.where, &dragRect);
  214.                             break;
  215.  
  216.                         case inContent:            /* body of application window: */
  217.                             if (whichWindow != FrontWindow())
  218.                                 SelectWindow(whichWindow); /* and make it active if not */
  219.                             CheckForKeyPress(myEvent.where);
  220.                             break;
  221.                     }
  222.                     break;
  223.  
  224.                 case updateEvt:                    /* Update the window. */
  225.                     if ((WindowPtr) myEvent.message == myWindow) {
  226.                         BeginUpdate((WindowPtr) myEvent.message);
  227.                         
  228.                         /* draw keyboard using current keyboard modifiers, 
  229.                            current KCHR, current keyboard KCAP 
  230.                              
  231.                              see Tech Note 263 for a better way to get the
  232.                              KCHR data under System 7 */
  233.                         
  234.                         DrawKeyCaps(myEvent.modifiers,
  235.                             GetScript(GetEnvirons(smKeyScript), smScriptKeys),
  236.                             gKcapNum, gKeycodesFlag);
  237.                         TEUpdate(&myWindow->portRect,gMyTE);
  238.                         EndUpdate((WindowPtr) myEvent.message);
  239.  
  240.                         /* set window title */
  241.                         NumToString(gKcapNum, tempStr);
  242.                         
  243.                         if (gKeycodesFlag) {
  244.                             /* set window title to "Virtual Keycodes for KCAP ID _" */
  245.                             tempStrHandle = GetString(128);
  246.                             if (tempStrHandle) {
  247.                                 p2cstr(*tempStrHandle);
  248.                                 strcpy((char*)tempStr2, (char*)*tempStrHandle);
  249.                                 strcat((char*)tempStr2, p2cstr(tempStr));
  250.                                 SetWTitle(myWindow, c2pstr((char*)tempStr2));
  251.                                 ReleaseResource((Handle)tempStrHandle);
  252.                             }
  253.                         }
  254.                         else {
  255.                             tempStrHandle = GetString(129);
  256.                             if (tempStrHandle) {
  257.                             
  258.                                 /* set window title to "Key Labels for KCAP ID _ and KCHR _" */
  259.                                 p2cstr(*tempStrHandle);
  260.                                 strcpy((char*)tempStr2, (char*)*tempStrHandle);  /* string */
  261.                                 strcat((char*)tempStr2, p2cstr(tempStr)); /* KCAP # */
  262.                                 ReleaseResource((Handle)tempStrHandle);
  263.                                 tempStrHandle = GetString(130);
  264.                                 if (tempStrHandle) {
  265.                                     p2cstr(*tempStrHandle);
  266.                                     strcat((char*)tempStr2, (char*)*tempStrHandle); /* string */
  267.                                     
  268.                                     /* get current KCHR number */
  269.                                     NumToString(GetScript(GetEnvirons(smKeyScript), smScriptKeys), tempStr);
  270.                                     strcat((char*)tempStr2, p2cstr(tempStr)); /* KCHR # */
  271.                                     SetWTitle(myWindow, c2pstr((char*)tempStr2));
  272.                                     ReleaseResource((Handle)tempStrHandle);
  273.                                 }
  274.                             }
  275.                         }
  276.                     }
  277.                     break;
  278.                             
  279.                 case keyDown:
  280.                 case autoKey:                    /* key pressed once or held down to repeat */
  281.                     if (myWindow == FrontWindow()) {
  282.                         theChar = (myEvent.message & charCodeMask); /* get the char */
  283.                         /* 
  284.                         **    If Command key down, do it as a Menu Command.
  285.                         */
  286.                         if (myEvent.modifiers & cmdKey)
  287.                             DoCommand(MenuKey(theChar));
  288.                         else {
  289.                             theChar = (myEvent.message & keyCodeMask) >> 8;
  290.                             CheckForKeyTyped(theChar);
  291.                         }
  292.                     }
  293.                     break;
  294.  
  295.             }
  296.         }
  297.     if ((myEvent.what != mouseDown) && oldModifiers != myEvent.modifiers  ) {
  298.         DrawKeyCaps(myEvent.modifiers,
  299.                     GetScript(GetEnvirons(smKeyScript), smScriptKeys),
  300.                     gKcapNum, gKeycodesFlag);
  301.                     oldModifiers = myEvent.modifiers;
  302.     }
  303.     TEIdle(gMyTE);
  304.     } while (!doneFlag);
  305.  
  306.     DisposeWindow (myWindow);
  307. }
  308.  
  309.  
  310. void SetUpMenus()
  311. {
  312.     short i, kcapMaxCount, tempInt;
  313.     Handle kcapHandle;
  314.     Str255 tempStr, kcapStr;
  315.     ResType tempResType;
  316.  
  317.     myMenus[appleM] = GetMenu(appleID);         /* read Apple menu from resource file */
  318.     AddResMenu(myMenus[appleM], 'DRVR');        /* add desk accessory names to Apple menu */
  319.     myMenus[fileM] = GetMenu(fileID);            /* read file menu from resource file */
  320.     myMenus[editM] = GetMenu(editID);            /* read edit menu from resource file */
  321.     DisableItem(myMenus[editM], 0);
  322.     myMenus[displayM] = GetMenu(displayID);            /* read display menu from resource file */
  323.  
  324.     /* add IDs of KCAP resources to display menu */
  325.     gKcapNum = *((char *) KbdType);  /* KCAP ID of current keyboard */
  326.  
  327.     *(short *)RomMapInsert = 0x0100;  /* use ROM resources, SetResLoad(false) */
  328.  
  329.     kcapMaxCount = CountResources('KCAP');
  330.     if (kcapMaxCount > 0) AppendMenu(myMenus[displayM], "\p(-!");
  331.  
  332.     /* add KCAP menu items */
  333.     for (i = 1; i <= kcapMaxCount; i++) {
  334.         *(short *)RomMapInsert = 0x0100;
  335.         kcapHandle = GetIndResource('KCAP', i);
  336.         if (kcapHandle) {
  337.             GetResInfo(kcapHandle, &tempInt, &tempResType, tempStr);
  338.             NumToString(tempInt, tempStr);
  339.             AppendMenu(myMenus[displayM],
  340.                 c2pstr(strcat(strcpy((char*)kcapStr, "KCAP "), p2cstr(tempStr))));
  341.             ReleaseResource(kcapHandle);
  342.             
  343.             if (tempInt == gKcapNum) {
  344.                 CheckItem(myMenus[displayM], i+2, true);
  345.                 gCurrDisplayItem = i+2;
  346.             }
  347.         }
  348.     }
  349.     gKeycodesFlag = false;                    /* not displaying keycodes on keys initially */
  350.     CheckItem(myMenus[displayM], 1, !gKeycodesFlag); /* mark that key labels are displayed */
  351.     
  352.     for (i = 0; i < menuCount; i++) 
  353.         InsertMenu(myMenus[i], 0);                 /* install menus in menu bar */
  354.     
  355.     
  356.     DrawMenuBar();                                /* and draw menu bar */
  357. }
  358.  
  359.  
  360. void ShowAboutMeDialog()
  361. {
  362.     DialogPtr    theDialog;
  363.     short        itemHit;
  364.  
  365.     theDialog = GetNewDialog(aboutMeDLOG, nil, (WindowPtr) -1);
  366.     ModalDialog(nil, &itemHit);
  367.     DisposDialog(theDialog);
  368. }
  369.  
  370.  
  371. /* DrawKeyCaps draws the key caps, given a set of
  372.    modifiers (in the high byte of the short) and
  373.    KCHR and KCAP resource IDs, using the current pen in
  374.    the current GrafPort 
  375.      
  376.      if keycodesFlag is true, the virtual keycodes are drawn
  377.      rather than the key labels.
  378.      
  379.    kcapPtr just bounces along the resource data as we 
  380.      parse it 
  381. */
  382.      
  383. /* see resource type definition on p. 14-101 of IM VI */
  384.  
  385. //------------------------------------------------------
  386.     void FrameSunkenRect(Rect *r1)
  387. //------------------------------------------------------
  388. {
  389.     short h,v;
  390.     Rect r =*r1;
  391.     
  392.     h = r.left;
  393.     v = r.top;
  394.     
  395.     RGBForeColor(&drkGray);
  396.     MoveTo(h,v);v = r.bottom;LineTo(h,v); //left edge
  397.     v=r.top;
  398.     MoveTo(h,v);h = r.right;LineTo(h,v); //top edge
  399.     
  400.     RGBForeColor(&liteGray);
  401.     h = r.right;
  402.     v = r.top;
  403.     MoveTo(h,v);v = r.bottom;LineTo(h,v); //right edge
  404.     h = r.left;
  405.     MoveTo(h,v);h = r.right;LineTo(h,v); //bottom edge
  406.     InsetRect(&r,1,1);
  407.     RGBForeColor((RGBColor*)RGBBlack);
  408.     FrameRect(&r);
  409. }
  410. //------------------------------------------------------
  411.     void FrameBumpRect(Rect *r1)
  412. //------------------------------------------------------
  413. {
  414.     short h,v,i;
  415.     Rect r = *r1;
  416.     
  417.     
  418.     InsetRect(&r,3,3);
  419.     for (i=0;i<2;i++){
  420.         h = r.left;
  421.         v = r.top;
  422.         
  423.         if (i==0) 
  424.             RGBForeColor(&tinge);
  425.         else
  426.             RGBForeColor(&liteGray);
  427.         
  428.         MoveTo(h,v);v = r.bottom;LineTo(h,v); //left edge
  429.         v=r.top;
  430.         MoveTo(h,v);h = r.right;LineTo(h,v); //top edge
  431.         
  432.         RGBForeColor(&drkGray);
  433.         h = r.right;
  434.         v = r.top;
  435.         MoveTo(h,v);v = r.bottom;LineTo(h,v); //right edge
  436.         h = r.left;
  437.         MoveTo(h,v);h = r.right;LineTo(h,v); //bottom edge
  438.         InsetRect(&r,-1,-1);
  439.     }
  440.     InsetRect(&r,-1,-1);
  441.     RGBForeColor((RGBColor*)RGBBlack);
  442.     FrameRect(&r);
  443. }
  444.  
  445. //--------------------------------------------------------
  446.     void         AdjustTE(Rect r)
  447. //--------------------------------------------------------
  448. {
  449.     InsetRect(&r,4,3);
  450.     (**gMyTE).destRect = r;
  451.     (**gMyTE).viewRect = r;
  452.     TECalText(gMyTE);
  453.     TEUpdate(&r,gMyTE);
  454. }
  455.  
  456. //--------------------------------------------------------
  457.     void DrawKeyCaps(short modifiers, short kchrNum, short kcapNum, Boolean keycodesFlag)
  458. //--------------------------------------------------------
  459. {
  460.     typedef struct {
  461.         char modifierMask;
  462.         char keyCode;
  463.         short deltaV;
  464.         short deltaH;
  465.     } KeyEntryRec;
  466.     
  467.     #define SHAPEMAXPTS 10  /* hopefully, fewer than 10 points per shape */
  468.         
  469.     Rect tempRect;
  470.     Point penPoint, currPoint, swapPoint;
  471.     Point shapePoint[SHAPEMAXPTS];
  472.     Handle kcapResHandle;
  473.     Ptr kcapPtr;
  474.  
  475.     
  476.     KeyEntryRec thisKeyEntryRec;
  477.     short mainIndex, shapeIndex, keyIndex, shapeTotal, shapeCount;
  478.     short modifiedKeyCode;
  479.     
  480.     FontInfo theFontInfo;
  481.     short fontHeight;
  482.     Point charLoc;
  483.     char theChar;
  484.     
  485.     RgnHandle keyshapeRgnHandle;
  486.     
  487.     Handle kchrResHandle;
  488.     long state;
  489.     
  490.     Str255 keycodeStr;
  491.     short saveTextSize;
  492.     //---------------------
  493.     
  494.     gNumberOfKeys =0;
  495.     GetFontInfo(&theFontInfo);
  496.     fontHeight = theFontInfo.ascent + theFontInfo.descent;
  497.     saveTextSize = myWindow->txSize;
  498.     RGBBackColor(&backGroundGray);
  499.     kchrResHandle = RGetResource('KCHR', kchrNum);
  500.     if (ResError() == noErr && kchrResHandle != nil) {
  501.         state = 0;
  502.     
  503.         kcapResHandle = RGetResource('KCAP', kcapNum);
  504.         if (ResError() == noErr && kcapResHandle != nil) {
  505.         
  506.             keyshapeRgnHandle = NewRgn();
  507.             
  508.             MoveHHi(kcapResHandle);
  509.             HLock(kcapResHandle);
  510.             kcapPtr = *kcapResHandle;
  511.             
  512.             /* draw boundary from origin */
  513.             tempRect = *((Rect *) kcapPtr);    
  514.             OffsetRect(&tempRect, - tempRect.left, -tempRect.top);
  515.             EraseRect(&tempRect);                            
  516.             FrameBumpRect(&tempRect);
  517.                                     
  518.             kcapPtr += sizeof(Rect);
  519.             
  520.             /* draw textedit area */
  521.             tempRect = *((Rect *) kcapPtr);    
  522.             FrameSunkenRect(&tempRect);
  523.             //FrameRect(&tempRect);    
  524.             AdjustTE(tempRect);                            
  525.             kcapPtr += sizeof(Rect);
  526.             
  527.             /* loop through main array */
  528.             mainIndex = *((short *) kcapPtr);
  529.             kcapPtr += sizeof(short);
  530.             for ( ; mainIndex>0; mainIndex--) {
  531.             
  532.                 /* loop through shape array - build array of points for this shape */
  533.                 shapeIndex = *((short *) kcapPtr);
  534.                 kcapPtr += sizeof(short);
  535.  
  536.                 shapeTotal = (shapeIndex < SHAPEMAXPTS ? shapeIndex + 1 : SHAPEMAXPTS);
  537.                 for (shapeCount=0; shapeIndex>-1; shapeIndex--, shapeCount++) {
  538.                     shapePoint[shapeCount] = *((Point *) kcapPtr);
  539.                     kcapPtr += sizeof(Point);
  540.                 }
  541.                 
  542.                 /* start drawing keys of this shape from 0,0 */
  543.                 MoveTo(0,0);
  544.                 
  545.                 /* loop through key array */
  546.                 keyIndex = *((short *) kcapPtr);
  547.                 kcapPtr += sizeof(short);
  548.                 for ( ; keyIndex>-1; keyIndex--) {
  549.                 
  550.                     /* get modifier mask, keyCode, and offset from previous key */                    
  551.                     thisKeyEntryRec = *((KeyEntryRec *) kcapPtr);
  552.                     kcapPtr += sizeof(KeyEntryRec);
  553.                     
  554.                     /* move the pen to the start of the key */
  555.                     Move(thisKeyEntryRec.deltaH, thisKeyEntryRec.deltaV);
  556.                     
  557.                     /* draw the key, composed of one or more rects */
  558.                     SetPt(&currPoint, 0, 0);
  559.                     //OpenRgn();
  560.                     
  561.                     for (shapeCount=0, shapeIndex=shapeTotal; shapeIndex; 
  562.                                 shapeIndex--, shapeCount++) {
  563.  
  564.                         /* set the rect, then reverse coordinates if necessary 
  565.                            to ensure it is not empty */
  566.                         SetRect(&tempRect, currPoint.h, currPoint.v, 
  567.                             shapePoint[shapeCount].h, shapePoint[shapeCount].v);
  568.                             
  569.                         if (tempRect.top > tempRect.bottom) {
  570.                             swapPoint.v = tempRect.top;
  571.                             tempRect.top = tempRect.bottom;
  572.                             tempRect.bottom = swapPoint.v;
  573.                         }
  574.                         if (tempRect.left > tempRect.right) {
  575.                             swapPoint.h = tempRect.left;
  576.                             tempRect.left = tempRect.right;
  577.                             tempRect.right = swapPoint.h;
  578.                         }
  579.                         
  580.                         /* move the rect to the pen location and add it to the region */
  581.                         currPoint = shapePoint[shapeCount];
  582.                         GetPen(&penPoint);
  583.                         OffsetRect(&tempRect, penPoint.h, penPoint.v);    
  584.                         FrameBumpRect(&tempRect);
  585.                     }
  586.                     
  587.                     /* draw the key frame */
  588.                     myKeys[gNumberOfKeys].keyRect = tempRect;
  589.                     
  590.                     //CloseRgn(keyshapeRgnHandle);
  591.                     //FrameRgn(keyshapeRgnHandle);
  592.                     SetEmptyRgn(keyshapeRgnHandle);
  593.                     
  594.                     /* convert the keyCode to a character code */
  595.                     /* mask out high bit of keyCode and add masked modifiers;
  596.                        KeyTrans stroke bit taken from modifier parameter */
  597.                     
  598.                          
  599.                     if (thisKeyEntryRec.keyCode & 0x80) 
  600.                         modifiers &= (((short) thisKeyEntryRec.modifierMask) << 8);
  601.                     else modifiers |= (((short) thisKeyEntryRec.modifierMask) << 8);
  602.                     
  603.                     modifiedKeyCode =
  604.                         ((thisKeyEntryRec.keyCode & 0x007F) | (modifiers & 0xFF80));
  605.                         
  606.                     myKeys[gNumberOfKeys].keyCode = modifiedKeyCode & 0x7F;    
  607.                     theChar = KeyTrans(*kchrResHandle, modifiedKeyCode, &state);
  608.                     myKeys[gNumberOfKeys].Ascii = theChar;
  609.                     
  610.                     if (!keycodesFlag) {
  611.                         /* center and draw the character */
  612.                         charLoc.v = 
  613.                             ((tempRect.top + tempRect.bottom) / 2) - (fontHeight / 2);
  614.                         charLoc.v += theFontInfo.ascent;
  615.                         charLoc.h = 
  616.                             ((tempRect.left + tempRect.right) / 2) - (CharWidth(theChar) / 2);
  617.                         MoveTo(charLoc.h, charLoc.v);
  618.                         DrawChar(theChar);
  619.                     } else {
  620.                         /* draw the virtual keycode instead of the key label */
  621.                         TextSize(9);
  622.                         NumToString(modifiedKeyCode & 0x7F, keycodeStr);
  623.                         charLoc.v = 
  624.                             ((tempRect.top + tempRect.bottom) / 2) - (fontHeight / 2);
  625.                         charLoc.v += theFontInfo.ascent;
  626.                         charLoc.h = 
  627.                             ((tempRect.left + tempRect.right) / 2) - (StringWidth(keycodeStr) / 2);
  628.                         MoveTo(charLoc.h, charLoc.v);
  629.                         DrawString(keycodeStr);
  630.                     }
  631.                     gNumberOfKeys++;
  632.                     /* reposition pen for next key */
  633.                     MoveTo(penPoint.h, penPoint.v);
  634.                 }
  635.             }
  636.             HUnlock(kcapResHandle);
  637.             DisposeRgn(keyshapeRgnHandle);
  638.             
  639.             /* release the KCAP and KCHR unless they're System resources */
  640.             if (HomeResFile(kcapResHandle) > 1) ReleaseResource(kcapResHandle);
  641.         }    
  642.         if (HomeResFile(kchrResHandle) > 1) ReleaseResource(kchrResHandle);
  643.         
  644.         TextSize(saveTextSize);
  645.     }
  646. }
  647.  
  648.  
  649. void DoCommand(long int mResult)
  650. {
  651.     short    theItem,                            /* menu item number from mResult low-order word */
  652.     theMenu;                            /* menu number from mResult high-order word */
  653.     Str255    name;                                /* desk accessory name */
  654.     int        tempInt;
  655.     ResType tempResType;
  656.     Str255 tempStr;
  657.     
  658.     Handle kcapHandle;
  659.     theItem = LoWord(mResult);                    /* call Toolbox Utility routines to */
  660.     theMenu = HiWord(mResult);                    /* set menu item number and menu */
  661.  
  662.     switch (theMenu) {                            /* switch on menu ID */
  663.  
  664.         case appleID:
  665.             if (theItem == aboutMeCommand)
  666.                 ShowAboutMeDialog();
  667.             else {
  668.                     GetItem(myMenus[appleM], theItem, name);
  669.                     tempInt = OpenDeskAcc(name);
  670.                     SetPort(myWindow);
  671.             }
  672.             break;
  673.  
  674.         case fileID:
  675.             if (theItem == quitItem)
  676.                 doneFlag = true;
  677.             break;
  678.  
  679.         case editID:
  680.             if (!SystemEdit(theItem - 1)) {    /* Pass the command on to the Desk Manager. */
  681.                 ; /* do nothing */
  682.             };
  683.             break;
  684.         
  685.         case displayID:
  686.                 
  687.                 if (gCurrDisplayItem != theItem) {
  688.                 
  689.                     if (theItem == 1) {
  690.                         
  691.                         /* display key labels */
  692.                         gKeycodesFlag = !gKeycodesFlag;
  693.                         CheckItem(myMenus[displayM], 1, !gKeycodesFlag);
  694.                         
  695.                     } else {
  696.     
  697.                         *(short *)RomMapInsert = 0x0100;  /* use ROM resources, SetResLoad(false) */
  698.                         kcapHandle = GetIndResource('KCAP', theItem - 2);
  699.     
  700.                         if (kcapHandle) {
  701.                             /* find the ID of the chosen KCAP */
  702.                             GetResInfo(kcapHandle, &gKcapNum, &tempResType, tempStr);
  703.                             ReleaseResource(kcapHandle);
  704.     
  705.                             CheckItem(myMenus[displayM], gCurrDisplayItem, false);
  706.                             CheckItem(myMenus[displayM], theItem, true);
  707.     
  708.                             gCurrDisplayItem = theItem;
  709.                         }
  710.                     }
  711.                     
  712.                     
  713.                     EraseRect(&myWindow->portRect);
  714.                     InvalRect(&myWindow->portRect);
  715.                 }
  716.                                                 
  717.             break;
  718.     }
  719.  
  720.     HiliteMenu(0);                                /* Unhighlight menu title */
  721.                                                 /* (highlighted by MenuSelect) */
  722. }
  723.